package com.guanghua.brick.db;

import java.io.Serializable;
import java.util.Map;

import com.guanghua.brick.html.Constant;


/**
 * web界面翻页器，JSP的Pager tag会根据该对象的值来显示界面的翻页器
 * 而后台的sql util会根据传入的pager来对sql进行分页处理
 * @author leeon
 */
public class PageInfo implements Serializable {
	/**
	 * PageInfo对象key的名字
	 */
	public static final String PI_KEY = "#_#PI_KEY#_#";
	
	public static final String PG_NO_PREFIX = ".endpageno";
	
	/**
	 * 默认的页大小
	 */
	public static int DEFAULT_PAGE_SIZE = 10;
	
	/**
	 * 定义求count的策略,每次都求,只求第一次,不求count
	 */
	public static final int COUNT_EVERY_TIME = 0;
	public static final int COUNT_FIRST_TIME = 1;
	public static final int COUNT_NO_TIME = 2;
	
	private int pageCount = 0;
	private int pageSize = DEFAULT_PAGE_SIZE;
	private int pageNo = 1;
	private int endPageNo = 1;
	private int rowCount = 0;
	private int countType = COUNT_EVERY_TIME;
	
	/**
	 * 只针对oracle数据库，翻页sql，如果是true，使用速度快，但排序可能有问题的分页方式
	 */
	private boolean oracleFastPageSQL = true;
	
	/**
	 * @param resultCount 要设置的 resultCount。
	 */
	public void setRowCount(int rowCount) {
		this.rowCount = rowCount;
		int pageCount = 0;
		if (rowCount % this.pageSize == 0) {
			pageCount = rowCount / this.pageSize;
		} else {
			pageCount = rowCount / this.pageSize + 1;
		}
		this.setPageCount(pageCount);
		
		if (this.pageNo < 1) this.pageNo = 1;
		if (this.pageNo > this.pageCount && this.pageCount > 0) this.pageNo = this.pageCount;
	}
	
	/**
	 * @return 返回 resultCount。
	 */
	public int getRowCount() {
		return rowCount;
	}
	/**
	 * @param pageNo 要设置的 pageNo。
	 */
	public void setPageNo(int pageNo) {
		if (pageNo > 0) this.pageNo = pageNo;
	}
	/**
	 * @return 返回 pageNo。
	 */
	public int getPageNo() {
		return pageNo;
	}
	/**
	 * @param pageSize 要设置的 pageSize。
	 */
	public void setPageSize(int pageSize) {
		if (pageSize > 0) this.pageSize = pageSize;		
	}
	/**
	 * @return 返回 pageSize。
	 */
	public int getPageSize() {
		return pageSize;
	}
	/**
	 * @param pageCount 要设置的 pageCount。
	 */
	protected void setPageCount(int pageCount) {
		this.pageCount = pageCount;
	}
	/**
	 * @return 返回 pageCount。
	 */
	public int getPageCount() {
		return pageCount;
	}
	
	private PageInfo(int pageSize, int pageNo, int endPageNo, int resultCount, int countType) {
		this.pageSize = pageSize;
		this.pageNo = pageNo;
		this.endPageNo = endPageNo;		
		this.countType = countType;
		//如果缓存count
		if (countType == COUNT_FIRST_TIME && resultCount != 0)
			this.setRowCount(resultCount);
	}
	
	public static PageInfo newInstance(Map req) {
		return newInstance(req, 
				Constant.GLOBE + "." + Constant.GLOBE_PAGESIZE, 
				Constant.GLOBE + "." + Constant.GLOBE_PAGENO, 
				Constant.GLOBE + "." + Constant.GLOBE_COUNT, 
				COUNT_EVERY_TIME);
	}
	
	public static PageInfo newInstance(Map req, int type) {
		return newInstance(req, 
				Constant.GLOBE + "." + Constant.GLOBE_PAGESIZE, 
				Constant.GLOBE + "." + Constant.GLOBE_PAGENO, 
				Constant.GLOBE + "." + Constant.GLOBE_COUNT, 
				type);
	}
	
	public static PageInfo newInstance(Map req, String prefix) {
		return newInstance(req, 
				prefix+ "." + Constant.GLOBE_PAGESIZE, 
				prefix + "." + Constant.GLOBE_PAGENO, 
				prefix + "." + Constant.GLOBE_COUNT, 
				COUNT_EVERY_TIME);
	}
	
	public static PageInfo newInstance(Map req, String prefix, int type) {
		return newInstance(req, 
				prefix+ "." + Constant.GLOBE_PAGESIZE, 
				prefix + "." + Constant.GLOBE_PAGENO, 
				prefix + "." + Constant.GLOBE_COUNT, 
				type);
	}
	
	private static PageInfo newInstance(Map req, String pageSizeKey, String pageNoKey, String countKey, int type) {
		int s = DEFAULT_PAGE_SIZE, n = 1, d = 1, c = 0;		
		
		//从页面传入的参数中获取pageSize
		if (pageSizeKey != null) {
			//在map中查找pageSizeKey
			if (req.get(pageSizeKey) != null) {
				pageSizeKey = toString(req.get(pageSizeKey));
			}
			
			try {
				//转型成整形
				s = Integer.parseInt(pageSizeKey);
			} catch (NumberFormatException e) {
				//e.printStackTrace();
			}
		}
		
		//从页面传入的参数中获取pageNoKey
		String endPageNoKey = pageNoKey + PG_NO_PREFIX;
		if (pageNoKey != null) {
			//在map中查找pageNoKey
			if (req.get(pageNoKey) != null) {
				pageNoKey = toString(req.get(pageNoKey));
			}
			
			//在map中查找endPageNoKey
			if (req.get(endPageNoKey) != null) {
				endPageNoKey = toString(req.get(endPageNoKey));
			} else {
				endPageNoKey = pageNoKey; 						
			}			
			
			try {
				n = Integer.parseInt(pageNoKey);
			} catch (NumberFormatException e) {
				//e.printStackTrace();
			}
			
			//转型结束页,如果不能转那么就和开始页相同
			try {
				d = Integer.parseInt(endPageNoKey);
			} catch (NumberFormatException e) {
				d = n;
			}			
			
		}
		
		//如果是只取第一次的count的情况
		if (type == COUNT_FIRST_TIME && countKey != null && req.get(countKey) != null) {
			String count = toString(req.get(countKey));
			try {
				c = Integer.parseInt(count);
			} catch (NumberFormatException e) {
			}
		}
			
		return new PageInfo(s, n, d, c, type);
	}
	
	
	/**
	 * 主要用于将单个的String数组转为String
	 * 取String数组的第一个值
	 * @param o
	 * @return
	 */
	private static String toString(Object o) {
		if (o instanceof String[]) {
			return ((String[])o)[0];
		} else if (o instanceof String) {
			return (String)o;
		} else {
			return o.toString();
		}
	}
	
	/**
	 * 重载Object的toString方法，利于log
	 */
	public String toString() {
		StringBuffer sb = new StringBuffer();
		
		sb.append("pageNo=").append(this.pageNo)
				.append(";pageSize=").append(this.pageSize)
				.append(";pageCount=").append(this.pageCount)
				.append(";resultCount=").append(this.rowCount);
		
		return sb.toString();
	}
	
	/**
	 * 重载pageinfo的equals方法，利于单元测试
	 */
	public boolean equals(Object other) {
		if (this == other) return true;
		if (other == null) return false;
		if (!(other instanceof PageInfo)) return false;
		
		PageInfo o = (PageInfo) other;
		
		if (this.getCountType() != o.getCountType()) return false;
		if (this.getPageNo() != o.getPageNo()) return false;
		if (this.getPageSize() != o.getPageSize()) return false;
		if (this.getRowCount() != o.getRowCount()) return false;
		if (this.getPageCount() != o.getPageCount()) return false;
		
		return true;
	}
	/**
	 * @return 返回记录集的第一条位置
	 */
	public int getFirstResult() {
		return (this.pageNo != 0)?this.pageSize * (this.pageNo - 1):0;
	}

	/**
	 * @return 返回记录集的数量
	 */
	public int getMaxResults() {
		return this.pageSize * (this.endPageNo - this.pageNo + 1);
	}
	/**
	 * @return
	 */
	public int getCountType() {
		return countType;
	}

	/**
	 * @param i
	 */
	public void setCountType(int i) {
		countType = i;
	}

	
	public boolean isOracleFastPageSQL() {
		return oracleFastPageSQL;
	}

	
	public void setOracleFastPageSQL(boolean oracleFastPageSQL) {
		this.oracleFastPageSQL = oracleFastPageSQL;
	}
	
	
}
